package com.hj.springframework4.io;

import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.Key;
import java.security.KeyFactory;
import java.time.*;
import java.util.*;
import java.util.function.Function;

/**
 * @Author : hujing
 * @Date: 2025/8/28 13:46
 * @Description:
 */
public class PropertyResolver {
    Logger logger = LoggerFactory.getLogger(getClass());
    
    Map<String,String> properties = new HashMap<>();
    Map<Class<?>, Function<String,Object>> converters = new HashMap<>();
    
    public PropertyResolver(Properties props){
        this.properties.putAll(System.getenv());
        Set<String> names = props.stringPropertyNames();
        for (String name : names) {
            properties.put(name,props.getProperty(name));
        }
        
        // 注册转换器
        converters.put(String.class,s->s);
        
        converters.put(boolean.class,Boolean::parseBoolean);
        converters.put(Boolean.class,Boolean::parseBoolean);
        
        converters.put(byte.class,Byte::parseByte);
        converters.put(Byte.class,Byte::parseByte);
        
        converters.put(short.class,Short::parseShort);
        converters.put(Short.class,Short::parseShort);

        converters.put(int.class, Integer::parseInt);
        converters.put(Integer.class, Integer::valueOf);

        converters.put(long.class, Long::parseLong);
        converters.put(Long.class, Long::valueOf);

        converters.put(float.class, Float::parseFloat);
        converters.put(Float.class, Float::valueOf);

        converters.put(double.class, Double::parseDouble);
        converters.put(Double.class, Double::valueOf);

        converters.put(LocalDate.class, LocalDate::parse);
        converters.put(LocalTime.class, LocalTime::parse);
        converters.put(LocalDateTime.class, LocalDateTime::parse);
        converters.put(ZonedDateTime.class, ZonedDateTime::parse);
        converters.put(Duration.class, Duration::parse);
        converters.put(ZoneId.class, ZoneId::of);
    }
    
    public <T> T getProperty(String key,Class<T> targetType){
        String value = getProperty(key);
        if (value == null){
            return null;
        }
        return convert(targetType,value);
    }
    
    <T> T convert(Class<?> clazz,String value){
        Function<String, Object> function = converters.get(clazz);
        if (function == null){
            throw new IllegalArgumentException("不支持的类型：" + clazz.getName());
        }
        return (T) function.apply(value);
    }
    
    public String getProperty(String key){
        PropertyExpr propertyExpr = parsePropertyExpr(key);
        if (propertyExpr != null){
            if (propertyExpr.getDefaultValue() != null){
                return getProperty(propertyExpr.getKey(),propertyExpr.getDefaultValue());
            }else{
                return getRequiredProperty(propertyExpr.getKey());
            }
        }
        String value = properties.get(key);
        if (value != null){
            return parseValue(value);
        }
        return value;
    }
    
    public String getProperty(String key,String defaultValue){
        String value = getProperty(key);
        if (value == null){
            return parseValue(defaultValue);
        }
        return value;
    }
    
    String parseValue(String value){
        PropertyExpr propertyExpr = parsePropertyExpr(value);
        if (propertyExpr == null){
            return value;
        }
        if (propertyExpr.getDefaultValue() != null){
            return getProperty(propertyExpr.getKey(),propertyExpr.getDefaultValue());
        }else{
            return getRequiredProperty(propertyExpr.getKey());
        }
    }
    
    String getRequiredProperty(String key){
        String value = properties.get(key);
        return Objects.requireNonNull(value,"未找到key的属性值");
    }
    
    public PropertyExpr parsePropertyExpr(String key){
        if (key.startsWith("${") && key.endsWith("}")){
            int n = key.indexOf(":");
            if (n == -1){// 没有默认值
                String k = key.substring(2, key.length()-1);
                return new PropertyExpr(k,null);
            }else{
                String k = key.substring(2,n);
                return new PropertyExpr(k,key.substring(n+1,key.length()-1));
            }
        }
        return null;
    }
}

@Data
class PropertyExpr{
    String key;
    String defaultValue;
    
    public PropertyExpr(String key,String defaultValue){
        this.key = key;
        this.defaultValue = defaultValue;
    }
}
